

int allocate(int words)
{
	int block;
	
	if( words + heapNext >= heapLimit ){
		
		//printf("requested %d words\n",words);
	
		//verifyHeap();
		//gc();
		PANIC("out of heap space");
	}
	
	block = heapNext;
	heapNext = heapNext + words*4;
	*(int*)heapNext = 2; //mark next word as a free block
	return block;
}

int instantiate(int class)
{
	int o, i;
	o = unpackSmInt(slotOf(class,3));
	i = ((o>>1) & 0x3F) + ((o>>10) & 0xC0) - 1; //0-255
	return instantiateN(class, i);
}

int instantiateN(int class, int size)
{
	int i,c,o,fmt, nWords, nBytes, f, namedSize;
	
	i = size;
	c = class;
	o = unpackSmInt(slotOf(c,3));
	fmt = (o >> 7) & 0xF; //format?
	
//	printString("new ");
//	printDecimal(heapLimit-heapNext);
//	printString("\n");
	
//	printf("size %d fmt %d\n", i, fmt);
	
	if(fmt==8){ //indexed bytes
	
		nBytes = i;
		nWords = (i+3)/4;
		
		o = allocate( nWords + 3 );
		*(int*)o = ( (nWords+1)<<2 ) | 0;
		o+=4;
		*(int*)o = c | 0;
		o+=4;
		switch(i%4){
			case 1: fmt = 8+3; break;
			case 2: fmt = 8+2; break;
			case 3: fmt = 8+1; break;
			case 0: fmt = 8+0; break;
		}
		*(int*)o = (fmt<<8) | (0<<2) | 0;
	
		for(i = 1; i <= nBytes; i++) setByteSlotOf(o,i,0);
		
		return o;
	}
	if(fmt==0 || fmt==1 || fmt==2){ //no fields, named pointers, indexed pointers
	
		nWords = i;
		
		o = allocate( nWords + 3 );
		*(int*)o = ( (nWords+1)<<2 ) | 0;
		o+=4;
		*(int*)o = c | 0;
		o+=4;
		*(int*)o = (fmt<<8) | (0<<2) | 0;
		
		for(i = 1; i <= nWords; i++) setSlotOf(o,i,nil);
		
		return o;
	}
	if(fmt==6) { //indexable words
		
		nWords = i;
		
		o = allocate( nWords + 3 );
		*(int*)o = ( (nWords+1)<<2 ) | 0;
		o+=4;
		*(int*)o = c | 0;
		o+=4;
		*(int*)o = (fmt<<8) | (0<<2) | 0;
		
		for(i = 1; i <= nWords; i++) setSlotOf(o,i,0);
		
		return o;
	}
	if(fmt==3 || fmt==4) { //named and indexed pointers
	
		f = unpackSmInt(slotOf(class,3));
		namedSize = ((f>>1) & 0x3F) + ((f>>10) & 0xC0) - 1;
		
		nWords = i + namedSize;
		
		o = allocate( nWords + 3 );
		*(int*)o = ( (nWords+1)<<2 ) | 0;
		o+=4;
		*(int*)o = c | 0;
		o+=4;
		*(int*)o = (fmt<<8) | (0<<2) | 0;
		
		for(i = 1; i <= nWords; i++) setSlotOf(o,i,nil);
		
		return o;
	}
	
	printf("%d \n", fmt);
	PANIC("other new: fmt");
	
	return -1;
}

int clone(int oop)
{
	//BOGUS I should probably be written in terms of chunk operations
	int s = sizeOf(oop);
	int h = headerSizeOf(oop);
	int t = s + h;
	
	int newObj = allocate( t );
	int returnObj = newObj + (4*(h-1));
	
	int src = oop - (4*(h-1));
	int dst = newObj;
	
	memcpy( (void*)dst, (void*)src, t*4 );
	
	return returnObj;
}

int firstObject()
{
	int object = heapStart;
	int header = *(int*)object; 
	
	switch(header&3){
		case 0: //3-word header
			object+=8; 
			break;
		case 1: //2-word header
			object+=4;
			break;
		case 2: //free space marker
			PANIC("unexpected free space in firstObject");
		case 3: //1-word (compact) header
			object+=0; 
			break;
	}
	if(object >= heapNext) PANIC("went past end of heap in firstObject");
	
	return object;
}

int objectAfter(int oop)
{
	if(isSmInt(oop)) PANIC("SmallInt in objectAfter");
	
	int object = oop + 4*sizeOf(oop) + 4;
	
	int header = *(int*)object; 
	switch(header&3){
		case 0: //3-word header
			object+=8; 
			break;
		case 1: //2-word header
			object+=4;
			break;
		case 2: //free space marker
			if(object >= heapNext) return 0; //end of heap
			PANIC("unexpected free space in objectAfter");
		case 3: //1-word (compact) header
			object+=0; 
			break;
	}
	if(object >= heapNext) PANIC("went past end of heap in objectAfter");
	
	return object;
}

/*
int firstChunk() { return heapStart; }
int firstObject() {
	int c = firstChunk();
	while( isFreeChunk(c) ) c = chunkAfter(c);
	return chunkToOop(c);
}
int isFreeChunk(int c){ return (*(int*)c & 3) == 2; }
int sizeOfChunk(int c){
	
}	

int objectAfter(int oop){

}

int chunkAfter(int c) {
	c += sizeOfChunk(c);
	if( *(int*)c == 2 ) return 0; //end of heap
	return c;
}
*/
